package com.sinosoft.platform.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ClassInvokeUtil {

    public static Object getMethodValue(Object obj, String methodName) throws Exception {
        methodName = "get" + upperFirst(methodName);
        Method method = getTargetMethod(obj, methodName);
        Object [] param = null;
        return method.invoke(obj, param);
    }

    public static void setMethodValue(Object obj, String methodName, Object value) throws Exception {
        methodName = "set" + upperFirst(methodName);
        Method method = getTargetMethod(obj, methodName);
        Object[] params = { value };
        method.invoke(obj, params);
    }

    public static List getAllFields(Object obj) {
        List filedList = new ArrayList();
        Class cls = obj.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            filedList.add(upperFirst(field.getName()));
        }
        return filedList;
    }

    public static Class getReturnType(Object obj, String methodName) {
        methodName = "get" + upperFirst(methodName);
        Method method = getTargetMethod(obj, methodName);
        return method.getReturnType();
    }

    public static Method getTargetMethod(Object facade, String facadeMethod) {
        Class type = facade.getClass();
        Method methods[] = type.getMethods();
        for (int i = 0; i < methods.length; i++) {
            if (facadeMethod.equals(methods[i].getName())) {
                Class[] paramTypes = methods[i].getParameterTypes();
                if (null == paramTypes || 0 == paramTypes.length || 1 == paramTypes.length) {
                    return methods[i];
                }
                else {
                    // 只调用参数个数为0或者1的方法，其他忽略
                    continue;
                }
            }
        }
        throw new RuntimeException("Invalid target method " + facadeMethod + " In Class" + facade);
    }

    public static Map initCommonDTO(Object commonDTO) throws Exception {
        Map rsMap = new HashMap();
        Class dtoClass = commonDTO.getClass();
        Field[] fields = dtoClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field filed = fields[i];
            String filedName = filed.getName();
            Object value = getMethodValue(commonDTO, upperFirst(filedName));
            rsMap.put(filedName.toUpperCase(), value);
        }
        return rsMap;
    }

    public static void objectToMap(Map source, Object target) throws Exception {
        Set keyset = source.keySet();
        Iterator iterator = keyset.iterator();

        while (iterator.hasNext()) {
            Object key = iterator.next();
            setMethodValue(target,String.valueOf(key),source.get(key));
        }
    }

    private static String upperFirst(String name) {
        return name.substring(0, 1).toUpperCase() + name.substring(1, name.length());
    }

    public static Object invokeService(Object obj, String methodName, Object requestObj) throws Exception {
        Method method = getTargetMethod(obj, methodName);
        Object[] reqObj = { requestObj };
        if(requestObj == null){
        	Object [] param = null;
            return method.invoke(obj, param);
        }else{
            return method.invoke(obj, reqObj);
        }
        
    }
    
    /**
     * 
     * 通过反射为对象设置属性值
     * @Title: reflectSetProperty 
     * @Description: TODO
     * @param obj
     * @param propertyName
     * @param param
     * @throws Exception
     */
 	@SuppressWarnings("rawtypes")
 	public static void reflectSetProperty(Object obj, String propertyName, Object param)
 			throws Exception {
 		String setMethodName = "set"
 				+ propertyName.substring(0, 1).toUpperCase()
 				+ propertyName.substring(1);
 		Field field = obj.getClass().getDeclaredField(propertyName);
 		Class typeClz = field.getType();
 		Method setMethod = obj.getClass().getDeclaredMethod(setMethodName,
 				typeClz);
 		setMethod.invoke(obj, param);
 	}

 	/**
 	 * 
 	 * 通过反射获取对象属性值
 	 * @Title: reflectGetProperty 
 	 * @Description: TODO
 	 * @param obj
 	 * @param propertyName
 	 * @return
 	 * @throws Exception
 	 */
 	public static Object reflectGetProperty(Object obj, String propertyName)
 			throws Exception {
 		String getMethodName = "get"
 				+ propertyName.substring(0, 1).toUpperCase()
 				+ propertyName.substring(1);
 		Method getMethod = obj.getClass().getDeclaredMethod(getMethodName);
 		return getMethod.invoke(obj);
 	}
 	
	/**
	 * 
	 * 用于判断Map中的value的类型是基本类型的包装类
	 * @Title: isSimpleTypeForMapValue 
	 * @Description: TODO
	 * @param clz
	 * @return
	 * @throws Exception
	 */
 	@SuppressWarnings("rawtypes")
 	public static boolean isSimpleTypeForMapValue(Class clz) throws Exception {
 		if (Boolean.class == clz) {
 			return true;
 		} else if (Character.class == clz) {
 			return true;
 		} else if (Short.class == clz) {
 			return true;
 		} else if (Integer.class == clz) {
 			return true;
 		} else if (Byte.class == clz) {
 			return true;
 		} else if (Long.class == clz) {
 			return true;
 		} else if (Double.class == clz) {
 			return true;
 		} else if (Float.class == clz) {
 			return true;
 		} else if (String.class == clz) {
 			return true;
 		} else {
 			return false;
 		}
 	}
}
